import { defineStore } from 'pinia'
import { getAuthButtonListApi } from '@/api/modules/login'
import piniaPersistConfig from '@/utils/piniaPersist'
import { EnumLocalStorageKey } from '@/enums/localStorage'
import type { RouteRecordNormalized, RouteRecordRaw } from 'vue-router'
import type { AuthMenuAndButtonState } from '@/types/auth-menu-and-button'
import type { MenuOptions } from '@/types/menu'
import usePermission from '@/hooks/usePermission'
import router from '@/router'
/**
 * @description 扁平化数组对象(主要用来处理路由菜单)
 * @param {Array} menuList 所有菜单列表
 * @return array
 */
function getFlatArr(menuList: RouteRecordRaw[]) {
  const newMenuList: RouteRecordRaw[] = JSON.parse(JSON.stringify(menuList))
  return newMenuList.reduce(
    (pre: RouteRecordRaw[], current: RouteRecordRaw) => {
      let flatArr = [...pre, current]
      if (current.children)
        flatArr = [...flatArr, ...getFlatArr(current.children)]
      return flatArr
    },
    []
  )
}

/**
 * @description 使用递归，过滤需要缓存的路由
 * @param {Array} menuList 所有菜单列表
 * @param {Array} cacheArr 缓存的路由菜单 name ['**','**']
 * @return array
 * */
function getKeepAliveRouterName(
  menuList: MenuOptions[],
  keepAliveArr: string[] = []
) {
  menuList.forEach(item => {
    item.meta.isKeepAlive && item.name && keepAliveArr.push(item.name)
    item.children?.length && getKeepAliveRouterName(item.children, keepAliveArr)
  })
  return keepAliveArr
}
/**
 * @description 使用递归，过滤出当前路径匹配的面包屑数组（即最后返回的数组里包括了当前路径及其所有祖先路径）
 * @param {String} path 当前访问地址
 * @param {Array} menuList 所有菜单列表
 * @returns array
 */
function getCurrentBreadcrumb(path: string, menuList: MenuOptions[]) {
  const tempPath: MenuOptions[] = []
  try {
    const getNodePath = (node: MenuOptions) => {
      tempPath.push(node)
      if (node.path === path) throw new Error('Find IT!')
      if (node.children?.length)
        node.children.forEach(item => getNodePath(item))
      tempPath.pop()
    }
    menuList.forEach(item => getNodePath(item))
  } catch (e) {
    return tempPath
  }
}

/**
 * @description 结合getCurrentBreadcrumb实现双重递归找出所有面包屑
 * @param {Array} menuList 所有菜单列表
 * @returns array
 */
function getAllBreadcrumbList(menuList: MenuOptions[]) {
  const handleBreadcrumbList: { [key: string]: any } = {}
  const loop = (menuItem: MenuOptions) => {
    if (menuItem?.children?.length)
      menuItem.children.forEach(item => loop(item))
    else
      handleBreadcrumbList[menuItem.path] = getCurrentBreadcrumb(
        menuItem.path,
        menuList
      )
  }
  menuList.forEach(item => loop(item))
  return handleBreadcrumbList
}

/**我这个是后端返回所有的路由表，权限判断还是交给前端来做 */
function getMenuList(menuList: RouteRecordRaw[]) {
  const permission = usePermission()
  const copyRouter = JSON.parse(JSON.stringify(menuList)) //菜单只渲染root的children

  //根据 order 排列路由在菜单中的顺序
  copyRouter.sort((a: RouteRecordNormalized, b: RouteRecordNormalized) => {
    return (a.meta.order || 0) - (b.meta.order || 0)
  })
  function travel(_routes: RouteRecordRaw[], layer: number) {
    if (!_routes) return null
    const collector: any = _routes.map(element => {
      // no access
      if (!permission.accessRouter(element)) {
        return null
      }

      // leaf node
      if (!element.children) {
        return element
      }

      // route filter hideInMenu true
      element.children = element.children.filter(x => x.meta?.isHide !== true)

      // Associated child node
      const subItem = travel(element.children, layer)
      if (subItem.length) {
        element.children = subItem
        return element
      }
      // the else logic
      if (layer > 1) {
        element.children = subItem
        return element
      }

      if (element.meta?.isHide === false) {
        return element
      }

      return null
    })
    return collector.filter(Boolean)
  }
  return travel(copyRouter, 0)
}

// AuthStore
const useAuthMenuAndButtonStore = defineStore({
  id: 'auth-menu-and-button',
  state: (): AuthMenuAndButtonState => ({
    // 按钮权限列表
    authButtonList: {},
    // menuList 作为动态路由，不会做持久化存储。这个是没有经过任何处理的后端直接返回的动态路由列表。
    authRouteList: []
  }),
  getters: {
    // 后端返回的菜单列表 ==> 左侧菜单栏渲染，需要去除 isHide == true
    showMenuListGet: state => getMenuList(state.authRouteList),
    // 扁平化之后的一维数组路由，主要用来添加动态路由
    flatRouteListGet: state => getFlatArr(state.authRouteList) as MenuOptions[],

    // 所有面包屑导航列表
    breadcrumbListGet() {
      return getAllBreadcrumbList(
        this.showMenuListGet as unknown as MenuOptions[]
      )
    },
    // 需要缓存的菜单 name，用作页面 keepAlive
    keepAliveRouterGet() {
      return getKeepAliveRouterName(
        this.showMenuListGet as unknown as MenuOptions[]
      )
    }
  },
  actions: {
    // getAuthButtonList
    async getAuthButtonList() {
      const { result } = await getAuthButtonListApi()
      this.authButtonList = result
    },

    //路由表在前端：
    getAuthRouteList() {
      const appRoute = router
        .getRoutes()
        .find(el => el.name === 'root') as RouteRecordNormalized //把root找出来
      this.authRouteList = appRoute.children
    }

    //后端返回路由表： getAuthMenuList
    // async getAuthRouteList() {
    // 	const { data } = await getAuthRouteListApi();
    // 	this.authRouteList = data;
    // },
  },
  // persist: piniaPersistConfig(EnumLocalStorageKey.AuthButtonList, ["routeName", "authButtonList"])
  persist: piniaPersistConfig(EnumLocalStorageKey.AuthButtonList, [
    'authButtonList'
  ])
})
export default useAuthMenuAndButtonStore
